package net.nutss.stunt;

import java.net.*;
import java.io.*;
import java.util.LinkedList;
import net.nutss.STUNTSelector;
import net.nutss.Continuation;
import static net.nutss.Control.log;

public class STUNTUDPSocket extends Thread {

	public DatagramSocket s = null;
	public Continuation con = null;
	private Object objLock=new Object();
	public LinkedList<DatagramPacket> aPackage=new LinkedList<DatagramPacket>();
	Exception er = null;
	private STUNTSelector sel=null;
	volatile boolean stop = false;
	int il = 0;

	public boolean hasData() {
		synchronized(objLock)
		{
			return !aPackage.isEmpty();
		}
	}

	public boolean isError() {
		return er != null;
	}

	public void stopSelect() {
		stop = true;
	}

	public void send(byte[] data,SocketAddress addr )throws SocketException, IOException
	{
		DatagramPacket ip = new DatagramPacket (data, data.length,addr);
		this.s.send(ip);
	}
	public void run() {
		stop = false;
		er = null;
		try {
			il = s.getSoTimeout();
			s.setSoTimeout(25);
		} catch (Exception e) {
			er = e;
			stop = true;
			return;
		}
		while (!stop && er == null) {
			if (!canRead()) {
				log.info("udp socket quit");
				stop = true;
				return;
			}

			try {
				byte[] buf = new byte[1500];
				DatagramPacket ip = new DatagramPacket(buf, buf.length);
				this.s.receive(ip);
				if(ip.getLength()>0)
				{
					synchronized(objLock)
					{
						aPackage.add(ip);
					}
				}
			} catch (SocketTimeoutException et) {
			} catch (Exception e) {
				er = e;
			}
		}
		try {
			s.setSoTimeout(il);
		} catch (Exception e) {
		}
	}

	public STUNTUDPSocket(DatagramSocket  s, Continuation con,STUNTSelector sel) {

		this.s = s;
		this.con = con;
		this.sel=sel;
		sel.add(this);
	}

	public byte[] readBytes() throws IOException {
			synchronized(objLock)
			{
				if(!aPackage.isEmpty())
				{
					DatagramPacket pkt=aPackage.removeFirst();
					byte[] bt=new byte[pkt.getLength()];
					System.arraycopy(pkt.getData(), pkt.getOffset(),bt, 0, pkt.getLength());
					return bt;
				}
			}
			throw new java.io.IOException("Not a validate socket");
	}

	public boolean isConnected() {
		return s != null && s.isConnected();
	}

	/*
	public void write(int val) throws IOException {
		if (canWrite())
			s.getOutputStream().write(val);
	}
	*/

	public void close() throws IOException {
		stopSelect();
		if (s != null && !s.isClosed())
			s.close();
		sel.remove(this);
	}


	public boolean canWrite() {
		return s != null && !s.isClosed();
	}

	public boolean canRead() {
		return s != null && !s.isClosed();
	}
}
